using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using MatrixFramework.Shared.Contracts.Monitoring;

namespace MatrixFramework.Shared.Application.Monitoring
{
    /// <summary>
    /// 健康检查应用服务
    /// 符合ABP vNext规范，提供可重用的健康检查功能
    /// </summary>
    public class HealthCheckAppService : ApplicationService, IHealthCheckAppService, ITransientDependency
    {
        private readonly ILogger<HealthCheckAppService> _logger;
        private readonly HealthCheckService _healthCheckService;
        private readonly IOpenTelemetryService _openTelemetryService;

        public HealthCheckAppService(
            ILogger<HealthCheckAppService> logger,
            HealthCheckService healthCheckService,
            IOpenTelemetryService openTelemetryService)
        {
            _logger = logger;
            _healthCheckService = healthCheckService;
            _openTelemetryService = openTelemetryService;
        }

        /// <summary>
        /// 获取简单健康状态
        /// </summary>
        public async Task<SimpleHealthCheckDto> GetSimpleHealthAsync()
        {
            using var operation = _openTelemetryService.StartOperation("HealthCheck.GetSimpleHealth");

            try
            {
                _openTelemetryService.AddEvent("health_check_started");

                var healthReport = await _healthCheckService.CheckHealthAsync();
                var isHealthy = healthReport.Status == HealthStatus.Healthy;

                var result = new SimpleHealthCheckDto
                {
                    Status = isHealthy ? "Healthy" : "Unhealthy",
                    Timestamp = DateTime.UtcNow,
                    TraceId = Activity.Current?.TraceId.ToString()
                };

                _openTelemetryService.AddEvent("health_check_completed", new Dictionary<string, object>
                {
                    ["health.status"] = result.Status,
                    ["components.checked"] = healthReport.Entries.Count
                });

                _openTelemetryService.RecordMetric("health_check_duration",
                    healthReport.TotalDuration.TotalMilliseconds, new Dictionary<string, object>
                    {
                        ["status"] = result.Status
                    });

                return result;
            }
            catch (Exception ex)
            {
                _openTelemetryService.RecordException(ex);
                _logger.LogError(ex, "获取简单健康状态失败");

                return new SimpleHealthCheckDto
                {
                    Status = "Unhealthy",
                    Timestamp = DateTime.UtcNow,
                    TraceId = Activity.Current?.TraceId.ToString()
                };
            }
        }

        /// <summary>
        /// 获取详细健康检查报告
        /// </summary>
        public async Task<DetailedHealthCheckDto> GetDetailedHealthAsync()
        {
            using var operation = _openTelemetryService.StartOperation("HealthCheck.GetDetailedHealth");

            try
            {
                _openTelemetryService.AddEvent("detailed_health_check_started");

                var healthReport = await _healthCheckService.CheckHealthAsync();

                var components = new Dictionary<string, ComponentHealthDto>();
                foreach (var entry in healthReport.Entries)
                {
                    components[entry.Key] = new ComponentHealthDto
                    {
                        Status = entry.Value.Status.ToString(),
                        Description = entry.Value.Description,
                        Duration = entry.Value.Duration,
                        Data = entry.Value.Data != null ? new Dictionary<string, object>(entry.Value.Data) : new Dictionary<string, object>(),
                        Exception = entry.Value.Exception?.Message
                    };
                }

                var result = new DetailedHealthCheckDto
                {
                    Status = healthReport.Status.ToString(),
                    Timestamp = DateTime.UtcNow,
                    TotalDuration = healthReport.TotalDuration,
                    Components = components,
                    TraceId = Activity.Current?.TraceId.ToString()
                };

                _openTelemetryService.AddEvent("detailed_health_check_completed", new Dictionary<string, object>
                {
                    ["health.status"] = result.Status,
                    ["components.count"] = components.Count,
                    ["total_duration_ms"] = result.TotalDuration.TotalMilliseconds
                });

                // 记录各组件的健康状态指标
                foreach (var component in components)
                {
                    _openTelemetryService.RecordMetric("component_health_status",
                        component.Value.Status == "Healthy" ? 1 : 0, new Dictionary<string, object>
                        {
                            ["component.name"] = component.Key,
                            ["component.status"] = component.Value.Status
                        });
                }

                return result;
            }
            catch (Exception ex)
            {
                _openTelemetryService.RecordException(ex);
                _logger.LogError(ex, "获取详细健康检查报告失败");

                return new DetailedHealthCheckDto
                {
                    Status = "Unhealthy",
                    Timestamp = DateTime.UtcNow,
                    TotalDuration = TimeSpan.Zero,
                    Components = new Dictionary<string, ComponentHealthDto>(),
                    TraceId = Activity.Current?.TraceId.ToString()
                };
            }
        }

        /// <summary>
        /// 获取特定组件的健康状态
        /// </summary>
        public async Task<ComponentHealthDto> GetComponentHealthAsync(string componentName)
        {
            using var operation = _openTelemetryService.StartOperation("HealthCheck.GetComponentHealth",
                new Dictionary<string, object>
                {
                    ["component.name"] = componentName
                });

            try
            {
                _openTelemetryService.AddEvent("component_health_check_started", new Dictionary<string, object>
                {
                    ["component.name"] = componentName
                });

                var healthReport = await _healthCheckService.CheckHealthAsync();

                if (!healthReport.Entries.ContainsKey(componentName))
                {
                    return new ComponentHealthDto
                    {
                        Status = "NotFound",
                        Description = $"组件 '{componentName}' 未找到",
                        Duration = TimeSpan.Zero,
                        Data = new Dictionary<string, object>(),
                        Exception = null
                    };
                }

                var entry = healthReport.Entries[componentName];
                var result = new ComponentHealthDto
                {
                    Status = entry.Status.ToString(),
                    Description = entry.Description,
                    Duration = entry.Duration,
                    Data = entry.Data != null ? new Dictionary<string, object>(entry.Data) : new Dictionary<string, object>(),
                    Exception = entry.Exception?.Message
                };

                _openTelemetryService.AddEvent("component_health_check_completed", new Dictionary<string, object>
                {
                    ["component.name"] = componentName,
                    ["component.status"] = result.Status,
                    ["component.duration_ms"] = result.Duration.TotalMilliseconds
                });

                _openTelemetryService.RecordMetric("component_health_check_duration",
                    result.Duration.TotalMilliseconds, new Dictionary<string, object>
                    {
                        ["component.name"] = componentName,
                        ["component.status"] = result.Status
                    });

                return result;
            }
            catch (Exception ex)
            {
                _openTelemetryService.RecordException(ex);
                _logger.LogError(ex, "获取组件健康状态失败: {ComponentName}", componentName);

                return new ComponentHealthDto
                {
                    Status = "Error",
                    Description = "检查组件健康状态时发生错误",
                    Duration = TimeSpan.Zero,
                    Data = new Dictionary<string, object>(),
                    Exception = ex.Message
                };
            }
        }
    }
}